﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Leo.JqueryGrid.Web.Models;
using Leo.JqueryGrid.Web.Services.Interfaces;
using OOGrid.Models;

namespace Leo.JqueryGrid.Web.Services.Fake
{
    public class ProductService : IProductService
    {
        private readonly Random _random = new Random();

        public List<Product> GetProducts(int count)
        {
            var products = new List<Product>();
            for (var i = 0; i < count; i++)
            {
                var product = new Product();
                product.ID = i + 1;
                product.Name = "Product - " + i.ToString("0000");
                product.Description = "description " + Guid.NewGuid() + Guid.NewGuid();
                product.CreatedDate = DateTime.Now.AddMinutes(_random.Next(-1000, 0));
                products.Add(product);
            }
            return products;
        }

        public List<Product> GetPagedProducts(OOGridFilter filter)
        {
            var products = new List<Product>();
            for (var i = 0; i < 1500; i++)
            {
                var product = new Product();
                product.ID = i + 1;
                product.Name = "Product - " + product.ID.ToString("000000");
                product.Description = "description " + Guid.NewGuid() + Guid.NewGuid();
                product.CreatedDate = DateTime.Now.AddMinutes(_random.Next(-1000, 0));
                products.Add(product);
            }
            if(filter.SortedColumns!=null)
            {
                var type = typeof(Product);
                var para = Expression.Parameter(type);
                foreach(var column in filter.SortedColumns)
                {
                    if (column == null)
                    {
                        continue;
                    }
                    var memberType = type.GetProperty(column.MemberPath).PropertyType;
                    var member = Expression.MakeMemberAccess(para, type.GetProperty(column.MemberPath));
                    IOrderedEnumerable<Product> orderedProducts = null;
                    if (memberType == typeof (string))
                    {
                        orderedProducts = GetOrderedProducts(products, column.IsAcending,
                                                             GetOrderBy<string>(member, para));
                    }
                    else if (memberType == typeof (int))
                    {
                        orderedProducts = GetOrderedProducts(products, column.IsAcending,
                                                             GetOrderBy<int>(member, para));
                    }
                    else
                    {
                        orderedProducts = GetOrderedProducts(products, column.IsAcending,
                                                             GetOrderBy<DateTime>(member, para));
                    }
                    products = orderedProducts.ToList();
                }
            }
            return products.Skip(filter.PageIndex*filter.PageSize).Take(filter.PageSize).ToList();
        }

        private Func<Product,TProperty> GetOrderBy<TProperty>(MemberExpression member, ParameterExpression parameter)
        {
            return Expression.Lambda<Func<Product, TProperty>>(member, parameter).Compile();
        } 

        private IOrderedEnumerable<Product> GetOrderedProducts<TPtoperty>(List<Product> products, bool isAscending, Func<Product, TPtoperty> order)
        {
            if(isAscending)
            {
                return products.OrderBy(order);
            }
            return products.OrderByDescending(order);
        } 
    }
}